﻿//-----------------------------------------------------------------------
// <copyright file="ColorPallettePresenter.xaml.cs" author="Artak Mkrtchyan">
//     Creative Commons - GNU General Public License (http://creativecommons.org/licenses/GPL/2.0/
// </copyright>
// <author>Artak Mkrtchyan</author>
// <email>mkArtak@gmail.com</email>
// <date>15/10/2012</date>
//-----------------------------------------------------------------------
using ConsoleHoster.Common.Utilities;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ConsoleHoster.View.Controls
{
	/// <summary>
	/// Interaction logic for ColorPallettePresenter.xaml
	/// </summary>
	public partial class ColorPallettePresenter : UserControl
	{
		public static DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorPallettePresenter), new PropertyMetadata(Colors.Red, new PropertyChangedCallback(OnSelectedColorChanged)));
		public static DependencyProperty PointingColorProperty = DependencyProperty.Register("PointingColor", typeof(Color), typeof(ColorPallettePresenter), new PropertyMetadata(Colors.Red));
		public static DependencyProperty AlphaProperty = DependencyProperty.Register("Alpha", typeof(byte), typeof(ColorPallettePresenter), new PropertyMetadata(byte.MaxValue, new PropertyChangedCallback(OnAlphaChanged)));
		public static DependencyProperty RelativeFillProperty = DependencyProperty.Register("RelativeFill", typeof(LinearGradientBrush), typeof(ColorPallettePresenter));

		private BitmapSource bitmapSource;

		private static void OnAlphaChanged(DependencyObject argSender, DependencyPropertyChangedEventArgs e)
		{
			ColorPallettePresenter tmpSender = argSender as ColorPallettePresenter;
			tmpSender.SelectedColor = Color.FromArgb(tmpSender.Alpha, tmpSender.SelectedColor.R, tmpSender.SelectedColor.G, tmpSender.SelectedColor.B);
		}

		private static void OnSelectedColorChanged(DependencyObject argSender, DependencyPropertyChangedEventArgs e)
		{
			ColorPallettePresenter tmpSender = argSender as ColorPallettePresenter;
			tmpSender.Alpha = tmpSender.SelectedColor.A;
		}

		public ColorPallettePresenter()
		{
			InitializeComponent();
			this.bitmapSource = this.imgPallette.Source as BitmapSource;
		}

		private void GenerateGradientFill()
		{
			Color tmpColor = this.SelectedColor;
			Color tmpHeaderColor;
			Color tmpFooterColor;
			GetGradientColors(tmpColor, out tmpHeaderColor, out tmpFooterColor);

			this.RelativeFill = new LinearGradientBrush
				{
					GradientStops = new GradientStopCollection
						{
							new GradientStop
								{
									Color = tmpHeaderColor,
									Offset=0
								},
							new GradientStop
								{
									Color = tmpColor,
									Offset = 0.5
								},
							new GradientStop
								{
									Color = tmpFooterColor,
									Offset = 1
								}
						}
				};
		}

		private static void GetGradientColors(Color tmpColor, out Color tmpHeaderColor, out Color tmpFooterColor)
		{
			tmpFooterColor = Color.FromArgb(tmpColor.A, 0, 0, 0);
			tmpHeaderColor = Color.FromArgb(tmpColor.A, 255, 255, 255);
		}

		private static void GetGradientColors2(Color tmpColor, out Color tmpHeaderColor, out Color tmpFooterColor)
		{
			if (tmpColor.R >= Math.Max(tmpColor.B, tmpColor.G))
			{
				tmpHeaderColor = Color.FromArgb(tmpColor.A, 0, tmpColor.G, tmpColor.B);
				tmpFooterColor = Color.FromArgb(tmpColor.A, 255, tmpColor.G, tmpColor.B);
			}
			else if (tmpColor.G >= Math.Max(tmpColor.R, tmpColor.B))
			{
				tmpHeaderColor = Color.FromArgb(tmpColor.A, tmpColor.R, 0, tmpColor.B);
				tmpFooterColor = Color.FromArgb(tmpColor.A, tmpColor.R, 255, tmpColor.B);
			}
			else
			{
				tmpHeaderColor = Color.FromArgb(tmpColor.A, tmpColor.R, tmpColor.G, 0);
				tmpFooterColor = Color.FromArgb(tmpColor.A, tmpColor.R, tmpColor.G, 255);
			}
		}

		private void imgPallette_MouseMove(object sender, MouseEventArgs e)
		{
			try
			{
				Point tmpMousePosition = Mouse.GetPosition(this.imgPallette);
				int tmpMappedCoordX = (int)(tmpMousePosition.X * this.bitmapSource.Width / this.imgPallette.ActualWidth);
				int tmpMappedCoordY = (int)(tmpMousePosition.Y * this.bitmapSource.Height / this.imgPallette.ActualHeight);
				CroppedBitmap tmpCrop = new CroppedBitmap(this.bitmapSource, new Int32Rect(tmpMappedCoordX, tmpMappedCoordY, 1, 1));

				byte[] tmpPixels = new byte[4];
				try
				{
					tmpCrop.CopyPixels(tmpPixels, 4, 0);
				}
				catch (Exception)
				{
				}

				this.PointingColor = Color.FromArgb(255, tmpPixels[2], tmpPixels[1], tmpPixels[0]);
			}
			catch (Exception)
			{
				// No logic here
			}
		}

		private void imgPallette_MouseUp(object sender, MouseButtonEventArgs e)
		{
			this.SelectedColor = this.PointingColor;
			this.GenerateGradientFill();
		}

		private void Slider_ValueChanged_1(object sender, RoutedPropertyChangedEventArgs<double> e)
		{
			Color tmpTop = this.RelativeFill.GradientStops[0].Color;
			Color tmpMid = this.RelativeFill.GradientStops[1].Color;
			Color tmpBottom = this.RelativeFill.GradientStops[2].Color;

			if (e.NewValue >= 50)
			{
				int tmpRelativePercent = ((int)e.NewValue - 50) * 2;
				this.SelectedColor = ColorUtilities.GetColorFromLinearRange(tmpMid, tmpTop, tmpRelativePercent);
			}
			else
			{
				int tmpRelativePercent = (50 - (int)e.NewValue) * 2;
				this.SelectedColor = ColorUtilities.GetColorFromLinearRange(tmpMid, tmpBottom, tmpRelativePercent);
			}
		}

		private void UserControl_Loaded_1(object sender, RoutedEventArgs e)
		{
			this.GenerateGradientFill();
		}

		public Color SelectedColor
		{
			get
			{
				return (Color)this.GetValue(SelectedColorProperty);
			}
			set
			{
				this.SetValue(SelectedColorProperty, value);
			}
		}

		public Color PointingColor
		{
			get
			{
				return (Color)this.GetValue(PointingColorProperty);
			}
			set
			{
				this.SetValue(PointingColorProperty, value);
			}
		}

		public byte Alpha
		{
			get
			{
				return (byte)this.GetValue(AlphaProperty);
			}
			set
			{
				this.SetValue(AlphaProperty, value);
			}
		}

		public LinearGradientBrush RelativeFill
		{
			get
			{
				return this.GetValue(RelativeFillProperty) as LinearGradientBrush;
			}
			set
			{
				this.SetValue(RelativeFillProperty, value);
			}
		}
	}
}
